package com.gaojinqi.base.common.util;

import com.gaojinqi.base.common.exception.BizRuntimeException;
import com.gaojinqi.base.common.model.PageReq;
import com.gaojinqi.base.common.model.PageResp;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.*;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页工具类
 *
 * @author gaojinqi
 * @version 1.0
 * @since 2020年04月09日
 */
@Slf4j
public class PageUtil {

    /**
     * 项目分页请求对象 ==> jpa Pageable
     */
    public static Pageable getPageable(PageReq pageReq) {
        // 空处理
        if (pageReq == null) {
            pageReq = new PageReq();
        }

        // 初始化分页参数
        int page = StringUtil.asInteger(pageReq.getPage(), 1) - 1;
        if (page < 0) {
            page = 0;
        }
        int size = StringUtil.asInteger(pageReq.getSize(), 10);
        if (size < 1) {
            size = 10;
        }
        // 加载排序信息（如果有
        if (StringUtils.hasText(pageReq.getSortBy())) {
            Sort.Direction direction = Sort.Direction.ASC;
            if (0 == StringUtil.asInteger(pageReq.getSortMode())) {
                direction = Sort.Direction.DESC;
            }
            // 组装排序实体
            Sort sort = Sort.by(direction, StringUtils.delimitedListToStringArray(pageReq.getSortBy(), ","));
            return PageRequest.of(page, size, sort);
        }

        return PageRequest.of(page, size);
    }

    /**
     * jpa Pageable ==> 项目分页响应对象
     */
    public static <T> PageResp<T> getPageResponse(Page<T> page) {
        PageResp<T> pageResp = new PageResp<>();
        pageResp.setPage(1);
        pageResp.setSize(0);
        pageResp.setTotal(0L);
        pageResp.setContent(Lists.newArrayList());
        if (page != null) {
            pageResp.setPage(page.getNumber() + 1);
            pageResp.setSize(page.getSize());
            pageResp.setTotal(page.getTotalElements());
            pageResp.setContent(page.getContent());
        }
        return pageResp;
    }


    /**
     * 将 Page 中的 entity 转成 BO
     * Page<Entity> ==> Page<Bo>
     */
    public static <E, B> Page<B> toBo(Page<E> sourcePage, Function<E, B> converter) {
        Assert.notNull(converter, "converter is must be not null!!!");
        Assert.notNull(sourcePage, "source page obj is must be not null!!!");
        List<B> content = sourcePage.getContent().stream().map(converter).collect(Collectors.toList());
        return new PageImpl<>(content, sourcePage.getPageable(), sourcePage.getTotalElements());
    }


    /**
     * 按指定次数分批查询
     *
     * @param batchHandler 用于业务逻辑
     * @param maxBatchSize 一批最大查询次数
     */
    public static void batchQuery(BatchHandler batchHandler, int maxBatchSize) {
        if (maxBatchSize < 1) {
            throw new BizRuntimeException("maxBatchSize is must be greater than 1!!!");
        }
        Assert.notNull(batchHandler, "batchHandler is must be not null!!!");
        int page = 1;
        long total;
        PageReq pageReq = new PageReq();
        pageReq.setPage(page);
        pageReq.setSize(maxBatchSize);
        do {
            total = batchHandler.batchQuery(pageReq);
            pageReq = new PageReq();
            pageReq.setPage(++page);
            pageReq.setSize(maxBatchSize);
        } while ((page - 1) * maxBatchSize < total);
    }

    @FunctionalInterface
    public interface BatchHandler {

        /**
         * @param pageReq 分页
         * @return 总条数
         */
        long batchQuery(PageReq pageReq);

    }

}
